#pragma once
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include<sys/socket.h>
#define SOCKET int
#endif
#include<list>
#include<openssl/ssl.h>

class SSLClient{
	static const unsigned int CACHESIZE=8192;
	public:
	//返回false则这轮保留并重置状态 会阻塞后续数据
	typedef bool(*DataCallback)(SSLClient*,void*);
	typedef void(*TimeoutCallback)(SSLClient*,void*);
	typedef struct{
		char* src;
		size_t size;
		DataCallback callback;
		void* arg;
	}DataPack;

	public:
	virtual ~SSLClient();
	//和服务端一起使用时无需调用
	static bool openlib();
	//和服务端一起使用时无需调用
	static void closelib();
	//线程不安全 多线程访问需要另外加锁 超时时会移除所有任务
	SSLClient(DataPack defaultpack,TimeoutCallback timeout,void* timeoutarg,
	time_t maxtime=120);
	//非阻塞通信 返回0初始化正常（不代表网络连接正常） -1出错
	int connecthost(const char* address,unsigned int port);
	//更新数据收发以及回调（如果数据发完收完）
	void update();
	static bool emptysendback(SSLClient*,void*);
	void senddata(DataPack p);
	//将数据接收加入队列
	void recvdata(DataPack p);
	//返回当前任务已经发送的数据量
	size_t getsent();
	//返回当前任务已经接收的数据量
	size_t getrecv();

	private:
	bool verified;
	time_t recordtime,maxtime;
	unsigned int sendcount,recvcount;
	size_t sendpos,recvpos;
	SOCKET _socket;
	SSL_CTX* ctx;
	SSL* ssl;
	void* timeoutarg;
	TimeoutCallback timeout;
	char cache[CACHESIZE];
	size_t pos,size;
	std::list<DataPack> pendingsend;//待发送包
	std::list<DataPack> pendingrecv;//待接收包
	DataPack defaultpack;
	//返回-1表示出错
	size_t getdata(char* buffer,size_t length);
};